<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>深拷贝浅拷贝</title>
</head>
<body>
  <div>
    <h4>区分深拷贝浅拷贝</h4>
    <div>如何区分深拷贝与浅拷贝，简单点来说，就是假设B复制了A，当修改A时，看B是否会发生变化，如果B也跟着变了，说明这是浅拷贝，拿人手短，如果B没变，那就是深拷贝。</div>
  </div>

  <script>
    let obj = {
      a: 100,
      b: [100, 200, 300],
      c: { x: 10 },
      d: /^\d+$/,
      e: {
        name: 'zhansan',
        age: 20
      }
    }

    // 一. 浅拷贝 
    // 拓展运算符
    // obj.a = 200;
    // let obj2 = {...obj};
    // console.log('obj2................'+obj2.a)
    
    // // 1.2遍历赋值操作 

    // let obj3 = {};
    // obj.a = 300;
    // for(let key in obj) {
    //   // hasOwnProperty() 方法会返回一个布尔值，指示对象自身属性中是否具有指定的属性（也就是，是否有指定的键）
    //   if(!obj.hasOwnProperty(key)) break;
    //   obj3[key] = obj[key]
    // }
    // console.log(obj3)

    // 2 深拷贝
    // 注意：在函数、日期、正则表达式时，JSON.stringify时，都会被转换成对象{} 
    // 会忽略undefined、symbol、函数；不能解决循环引用；不能处理正则、new Date()
   
    // let obj4 = JSON.parse(JSON.stringify(obj));
    // obj.a = 400;
    // console.log(obj, obj4) // 所以 d 正则则为 {}

    // 2.2 深拷贝
    function deepClone(obj) {
      // 过滤一些特殊情况
      if(obj === null) return null;
      if(typeof obj !== "object") return obj;
      if(obj instanceof RegExp) { // 正则
          return new RegExp(obj);
      }
      if(obj instanceof Date) { // 日期
          return new Date(obj);
      }
      // let newObj = {}
      // let newObj = new Object()
      let newObj = new obj.constructor; // 不直接创建空对象的目的：克隆的结果和之前保持所属类  =》 即能克隆普通对象，又能克隆某个实例对象
      for(let key in obj) {
        // 对象自身属性中是否具有指定的属性（也就是，是否有指定的键）。
          if(obj.hasOwnProperty(key)) {
            newObj[key] = deepClone(obj[key]);
          }
      }
      return newObj;
    }

    // let obj5 = deepClone(obj);
    // obj.a = 200;
    // console.log(obj5)


  function deepClone(obj) {
    if (typeof obj != 'object') return obj;
    var temp = Array.isArray(obj) ? [] : {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            if (obj[key] && typeof obj[key] == 'object') {
              // 对象里仍然包含着 对象 继续遍历
              temp[key] = deepClone(obj[key])
            } else {
              temp[key] = obj[key];
            }
        }
      }
      return temp;
    }
    let info = {
      name: 'yimwu',
      tel: '134xxxxx320',
      address: {
        home: 'jy',
        company: 'gz'
      }
    }

    let infoCopy = deepClone(info)


    function deepClone3(obj) {
      if(obj === null) return null;
      if(typeof obj !== 'object') return obj;
      if(typeof obj === RegExp) {
        return new RegExp(obj)
      }

      if(typeof obj === Date) {
        return new Date(obj)
      }

      let newObj = new obj.constructor;

      for(let key in obj) {
        if(obj.hasOwnProperty(key)) {
          if(obj[key] && typeof obj[key] == 'object') {
            newObj[key] = deepClone3(obj[key])
          } else {
            newObj[key] = obj[key]
          }
        }
      }

      return newObj
    }

  </script>
  
</body>
</html>